using Aurora.EventBus.Dependencies;
using Aurora.EventBus.Sources;
using Aurora.EventBus.Storage;

namespace Aurora.EventBus.Internal;

/// <summary>
/// 基于内存通道事件发布者（默认实现）
/// </summary>
internal sealed partial class ChannelEventPublisher : IEventPublisher
{
    /// <summary>
    /// 事件源存储器
    /// </summary>
    private readonly IEventSourceStorage _eventSourceStorage;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="eventSourceStorage">事件源存储器</param>
    public ChannelEventPublisher(IEventSourceStorage eventSourceStorage)
    {
        _eventSourceStorage = eventSourceStorage;
    }

    /// <summary>
    /// <see cref="IEventPublisher.PublishAsync(IEventSource)"/>
    /// </summary>
    public async Task PublishAsync(IEventSource @event)
    {
        await _eventSourceStorage.WriteAsync(@event, @event.CancellationToken);
    }

    public Task PublishDelayAsync(IEventSource @event, long delay)
    {
        Task.Factory.StartNew(async () =>
        {
            await Task.Delay(TimeSpan.FromMilliseconds(delay), @event.CancellationToken);

            await _eventSourceStorage.WriteAsync(@event, @event.CancellationToken);
        }, @event.CancellationToken);
        return Task.CompletedTask;
    }

    public async Task PublishAsync(string eventId, object payload = default,
        CancellationToken cancellationToken = default)
    {
        await PublishAsync(new ChannelEventSource(eventId, payload, cancellationToken));
    }

    public async Task PublishAsync(Enum eventId, object payload = default,
        CancellationToken cancellationToken = default)
    {
        await PublishAsync(new ChannelEventSource(eventId, payload, cancellationToken));
    }

    public async Task PublishDelayAsync(string eventId, long delay, object payload = default,
        CancellationToken cancellationToken = default)
    {
        await PublishDelayAsync(new ChannelEventSource(eventId, payload, cancellationToken), delay);
    }

    public async Task PublishDelayAsync(Enum eventId, long delay, object payload = default,
        CancellationToken cancellationToken = default)
    {
        await PublishDelayAsync(new ChannelEventSource(eventId, payload, cancellationToken), delay);
    }
}